package application.models.datalayer;

import java.io.IOException;

/**
 * This class handles any communication with the data layer
 * 
 * @author Philip Rasmussen & Morten Therkildsen
 */

public abstract class DataLayerCommunicator {
	
	/**
	 * Returns a DataLayerCommunicator (Singleton pattern)
	 * A new one is created at first call
	 * Subsequent calls reuses the already created instance
	 * 
	 * @return	a DataLayerCommunicator
	 */
	public static DataLayerCommunicator getInstance(){
		
		return DatabaseCommunicator.getInstance(); 
	}

	/**
	 * Get meta information about the attributes of a data set (quantity, their data types, values, etc.)
	 * 
	 * @param setName		The name of the set to retrieve the information for
	 * @return				An array of attribute objects/descriptions
	 * @throws IOException if the operation fails
	 */
	public abstract Attribute[] getDataSetDescription(String setName) throws IOException;
	
	/**
	 * Queries the data layer for data. Returns all attributes for the matched entity
	 * 
	 * @param setName		The name of the set to retrieve information for. Cannot be null or empty.
	 * @param conditions	Any conditions used to narrow down the results.
	 * @return				A 2-dimensional array containing the attribute objects that satisfies conditions
	 * @throws IOException if the operation fails
	 */
	public abstract Attribute[][] readFromDataLayer(String setName, DataCondition[] conditions) throws IOException;
	
	/**
	 * Queries the data layer for data. Returns only the specified attributes for the matched entities.
	 * If no attributes are specified (null), all will be queried.
	 * 
	 * @param setName		The name of the set to retrieve information for. Cannot be null or empty.
	 * @param conditions	Any conditions used to narrow down the results.
	 * @param attributeNames	The names of the attribute objects to return
	 * @return				A 2-dimensional array containing the attribute objects defined by attributeNames that satisfies conditions
	 * @throws IOException if the operation fails
	 */
	public abstract Attribute[][] readFromDataLayer(String setName, DataCondition[] conditions, String[] attributeNames) throws IOException;
	
	/**
	 * Updates an existing entity in the data layer or creates one if it does not already exist.
	 * Applies changes in attributes for the entity
	 * 
	 * @param setName		The name of the set to write to. Cannot be null or empty
	 * @param values		The attributes and their new values. Cannot be null
	 * @return				The id attribute of the updated entity.
	 * @throws IOException if the operation fails, for instance if mandatory attributes are missing or have no values
	 */
	public abstract Attribute writeToDataLayer(String setName, Attribute[] values) throws IOException;
	
	/**
	 * Deletes an existing entity in the data layer.
	 * 
	 * @param setName 		The name of the entity to delete. Cannot be null or empty
	 * @throws IOException	if the operation fails
	 */
	public abstract void deleteFromDataLayer(String setName, DataCondition[] conditions) throws IOException;
}
